///////////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------------
#include <Config.h>
#include <Texture/TGATextureLoader.h>
#include <Texture/TextureManager.h>
#include <Input/InputManager.h>
#include <Scene/ObjectLoaders/OBJObjectLoader.h>
#include <Scene/ObjectLoaders/MS3DObjectLoader.h>
#include <Material/MaterialManager.h>
#include <Shader/ShaderManager.h>
#include <Profiling/ProfilingManager.h>
#include <Scripting/ScriptManager.h>
#include <SettingsManager.h>
#include <glInfo.h>
#include <string.h>
#if defined(LINUX)
	#include <GL/glx.h>
#endif

//-----------------------------------------------------------------------------

void SetVSync(bool sync)
{
#if defined(WIN32)
	if(strstr((const char*)glGetString(GL_EXTENSIONS),"WGL_EXT_swap_control"))
	{
		typedef bool (APIENTRY *PFNWGLSWAPINTERVALFARPROC)(int);
		PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT = 0;
		wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress("wglSwapIntervalEXT");
		if(wglSwapIntervalEXT)
		{
			wglSwapIntervalEXT(sync);
			DEBUG_OUT("runs wglSwapIntervalEXT");
		}
	}
	else
	{
		//printf("EXT:\n%s\n",glGetString(GL_EXTENSIONS));
		DEBUG_OUT("Extension WGL_EXT_swap_control not supported!");
	}
#elif defined(LINUX)
	typedef int (*PFNGLXSWAPINTERVALSGIPROC)(int);
	PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI;
	glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddress((const GLubyte*)"glXSwapIntervalSGI");
	if(glXSwapIntervalSGI)
	{
		if(glXSwapIntervalSGI(sync))
		{
			DEBUG_OUT("glXSwapIntervalSGI error");
		}
	}
#endif
	GL_CHECK_ERRORS();
}

//-----------------------------------------------------------------------------

#if defined(DEBUG)
void Debug_OSPrint(  char* debugMsg )
{
	if( DEBUG )
	{
		printf( debugMsg );
#ifdef WIN32
		OutputDebugStringA(debugMsg);
#endif
	}
}

//-----------------------------------------------------------------------------

void Debug_LogFull( char* debugSourceFile, int line, char* debugMsg )
{
	if( DEBUG )
	{
		//SDK_ASSERTMSG( strlen(debugMsg) < DEBUG_MESSAGEMAX_LENGTH , "Debug_Log message is longer than DEBUG_MESSAGEMAX_LENGTH");

		//DEBUG_OUT( "Log->" );
		//DEBUG_OUT( "[%i] ", Game::GetGame()->GetTime() );
		DEBUG_OUT( debugSourceFile );
		DEBUG_OUT( "(%i) : \t", line );
		DEBUG_OUT( debugMsg );
		DEBUG_OUT( "\n" );
	}
}

//----------------------------------------------------------------------------------------------------------

void Debug_Warning( char* debugMsg )
{
	if( DEBUG )
	{
		//SDK_ASSERTMSG( strlen(debugMsg) < DEBUG_MESSAGEMAX_LENGTH , "Debug_Log message is longer than DEBUG_MESSAGEMAX_LENGTH");

		Debug_ChangeColor( CONSOLECOLOR_GREEN2 );
		DEBUG_OUT( "WARNING!  " );
		Debug_ChangeColor( CONSOLECOLOR_GREEN );
		DEBUG_OUT( debugMsg );
		Debug_ChangeColor( CONSOLECOLOR_WHITE );
		DEBUG_OUT( "\n" );
		Debug_ChangeColor( CONSOLECOLOR_RESET );
	}
}

//----------------------------------------------------------------------------------------------------------

void Debug_Error( char* debugMsg )
{
	if( DEBUG )
	{
		//SDK_ASSERTMSG( strlen(debugMsg) < DEBUG_MESSAGEMAX_LENGTH , "Debug_Log message is longer than DEBUG_MESSAGEMAX_LENGTH");

		Debug_ChangeColor( CONSOLECOLOR_RED2 );
		DEBUG_OUT( "ERROR!  " );
		Debug_ChangeColor( CONSOLECOLOR_RED );
		DEBUG_OUT( debugMsg );
		Debug_ChangeColor( CONSOLECOLOR_WHITE );
		DEBUG_OUT( "\n" );
		Debug_ChangeColor( CONSOLECOLOR_RESET );
	}
}

//----------------------------------------------------------------------------------------------------------

void Debug_ChangeColor( eConsoleColor c )
{
#ifdef WIN32
	HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
	int color = 0;
switch( c )
	{
	case CONSOLECOLOR_WHITE	:	color =	FOREGROUND_RED   | FOREGROUND_GREEN | FOREGROUND_BLUE;								break;
	case CONSOLECOLOR_WHITE2:	color =	FOREGROUND_RED   | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;		break;
	case CONSOLECOLOR_RED	:	color =	FOREGROUND_RED | FOREGROUND_INTENSITY;												break;
	case CONSOLECOLOR_RED2	:	color =	FOREGROUND_RED;																		break;
	case CONSOLECOLOR_GREEN	:	color =	FOREGROUND_GREEN | FOREGROUND_INTENSITY;											break;
	case CONSOLECOLOR_GREEN2:	color =	FOREGROUND_GREEN;																	break;
	case CONSOLECOLOR_BLUE	:	color =	FOREGROUND_BLUE | FOREGROUND_INTENSITY;												break;
	case CONSOLECOLOR_BLUE2	:	color =	FOREGROUND_BLUE;																	break;
	case CONSOLECOLOR_BG	:	color =	FOREGROUND_BLUE  | FOREGROUND_GREEN | FOREGROUND_INTENSITY;							break;
	case CONSOLECOLOR_RB	:	color =	FOREGROUND_RED   | FOREGROUND_BLUE | FOREGROUND_INTENSITY;							break;
	case CONSOLECOLOR_RG	:	color =	FOREGROUND_RED   | FOREGROUND_GREEN | FOREGROUND_INTENSITY;							break;
	case CONSOLECOLOR_BG2	:	color =	FOREGROUND_BLUE  | FOREGROUND_GREEN;												break;
	case CONSOLECOLOR_RB2	:	color =	FOREGROUND_RED   | FOREGROUND_BLUE;													break;
	case CONSOLECOLOR_RG2	:	color =	FOREGROUND_RED   | FOREGROUND_GREEN;												break;
	}
#elif LINUX
	switch( c )
	{
	case CONSOLECOLOR_RESET	:
		printf("\033[0m");
	break;
	case CONSOLECOLOR_WHITE	:
		printf("\033[01;37m");
	break;
	case CONSOLECOLOR_WHITE2:
		printf("\033[01;37m");
	break;
	case CONSOLECOLOR_RED	:
		printf("\033[01;31m");
	break;
	case CONSOLECOLOR_RED2	:															
		printf("\033[22;31m");
	break;
	case CONSOLECOLOR_GREEN	:
		printf("\033[01;32m");
	break;
	case CONSOLECOLOR_GREEN2:
		printf("\033[22;32m");
	break;
	case CONSOLECOLOR_BLUE	:
		printf("\033[01;34m");
	break;
	case CONSOLECOLOR_BLUE2	:
		printf("\033[22;34m");
	break;
	}
#endif
}

#endif //debug

//-----------------------------------------------------------------------------

void checkForGLErrors()
{
	GLenum errCode;
	const GLubyte* errString;
	errCode = glGetError();
	if( errCode != GL_NO_ERROR )
	{
		while( errCode != GL_NO_ERROR )
		{
			errString = gluErrorString(errCode);
			printf( (char*) errString );
			errCode = glGetError();
		}
	}
	//else
	//{
	//	DEBUG_OUT( "No errors.\n" );
	//}
}

//-----------------------------------------------------------------------------

float oglVersion()
{
	return atof((const char*)glGetString(GL_VERSION));
}

//-----------------------------------------------------------------------------

bool		MGL_init()
{
	bool result = true;

	//managers
	result &= glInfo::GetInstance() != NULL;
	result &= SettingsManager::GetInstance() != NULL;
	result &= InputManager::GetInstance() != NULL;
	result &= TextureManager::GetInstance() != NULL;
	result &= MaterialManager::GetInstance() != NULL;
	result &= ShaderManager::GetInstance() != NULL;
	result &= ScriptManager::GetInstance() != NULL;
#ifdef	__MGL_USE_PROFILING_TOOLS__
	result &= ProfilingManager::GetInstance() != NULL;
#endif

	//texture loaders
	result &= TGATextureLoader::GetInstance() != NULL;

	//object loaders
	result &= MS3DObjectLoader::GetInstance() != NULL;
	result &= OBJObjectLoader::GetInstance() != NULL;

	return result;
}

void		MGL_exit()
{
	//managers
	glInfo::ReleaseInstance();
	InputManager::ReleaseInstance();
	TextureManager::ReleaseInstance();
	MaterialManager::ReleaseInstance();
	ShaderManager::ReleaseInstance();
	ScriptManager::ReleaseInstance();
#ifdef	__MGL_USE_PROFILING_TOOLS__
	ProfilingManager::ReleaseInstance();
#endif

	////texture loaders
	//TGATextureLoader::ReleaseInstance();

	////object loaders
	//MS3DObjectLoader::ReleaseInstance();
	//OBJObjectLoader::ReleaseInstance();
	SettingsManager::ReleaseInstance();
}

//-----------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////
